package com.snail.clouds.storage.providers.tianyi_tv;

import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;

import java.util.Map;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.util.logging.Logger;
import java.util.logging.Level;

/**
 * 天翼TV专用HTTP工具类
 * 基于OkHttp实现，提供统一的HTTP请求处理
 */
public class HttpUtils {
    
    // 日志记录器
    private static final Logger logger = Logger.getLogger(HttpUtils.class.getName());
    
    // 默认超时设置
    private static final int CONNECT_TIMEOUT = 10; // 连接超时10秒
    private static final int READ_TIMEOUT = 60;   // 读取超时60秒
    
    // 调试标志，可通过系统属性控制
    private static final boolean DEBUG_ENABLED = Boolean.parseBoolean(
        System.getProperty("tianyi.tv.debug", "false"));
    
    /**
     * 发送GET请求
     * 
     * @param url 请求URL
     * @param headers 请求头
     * @param params 请求参数
     * @return 响应结果
     * @throws Exception 请求异常
     */
    public static String get(String url, Map<String, String> headers, Map<String, Object> params) throws Exception {
        try {
            HttpRequest request = HttpUtil.createGet(url)
                    .timeout(CONNECT_TIMEOUT * 1000);
            
            // 添加请求头
            if (headers != null && !headers.isEmpty()) {
                request.addHeaders(headers);
            }
            
            // 添加请求参数
            if (params != null && !params.isEmpty()) {
                request.form(params);
            }
            
            HttpResponse response = request.execute();
            
            if (response.getStatus() != 200) {
                throw new Exception("HTTP请求失败: " + response.getStatus());
            }
            
            return response.body();
        } catch (Exception e) {
            throw new Exception("GET请求失败: " + e.getMessage(), e);
        }
    }
    
    /**
     * 发送POST请求
     * 
     * @param url 请求URL
     * @param headers 请求头
     * @param params 请求参数
     * @return 响应结果
     * @throws Exception 请求异常
     */
    public static String post(String url, Map<String, String> headers, Map<String, Object> params) throws Exception {
        try {
            HttpRequest request = HttpUtil.createPost(url)
                    .timeout(CONNECT_TIMEOUT * 1000);
            
            // 添加请求头
            if (headers != null && !headers.isEmpty()) {
                request.addHeaders(headers);
            }
            
            // 添加请求参数
            if (params != null && !params.isEmpty()) {
                request.form(params);
            }
            
            HttpResponse response = request.execute();
            
            if (response.getStatus() != 200) {
                throw new Exception("HTTP请求失败: " + response.getStatus());
            }
            
            return response.body();
        } catch (Exception e) {
            throw new Exception("POST请求失败: " + e.getMessage(), e);
        }
    }
    
    /**
     * 发送POST请求（支持分离的查询参数和表单参数）
     *
     * @param url 请求URL
     * @param headers 请求头
     * @param queryParams 查询参数
     * @param formParams 表单参数
     * @return 响应结果
     * @throws Exception 请求异常
     */
    public static String postWithSeparateParams(String url, Map<String, String> headers,
                                            Map<String, Object> queryParams, Map<String, Object> formParams) throws Exception {
        try {
            HttpRequest request = HttpUtil.createPost(url)
                    .timeout(CONNECT_TIMEOUT * 1000);
            
            // 添加请求头
            if (headers != null && !headers.isEmpty()) {
                request.addHeaders(headers);
            }
            
            // 添加查询参数
            if (queryParams != null && !queryParams.isEmpty()) {
                request.form(queryParams);
            }
            
            // 添加表单参数
            if (formParams != null && !formParams.isEmpty()) {
                request.form(formParams);
            }
            
            HttpResponse response = request.execute();
            
            if (response.getStatus() != 200) {
                throw new Exception("HTTP请求失败: " + response.getStatus());
            }
            
            return response.body();
        } catch (Exception e) {
            throw new Exception("POST请求失败: " + e.getMessage(), e);
        }
    }
    
    /**
     * 发送PUT请求（用于文件上传）
     * 
     * @param url 请求URL
     * @param headers 请求头
     *param data 上传数据
     * @return 响应结果
     * @throws Exception 请求异常
     */
    public static String put(String url, Map<String, String> headers, byte[] data) throws Exception {
        try {
            HttpRequest request = HttpUtil.createRequest(cn.hutool.http.Method.PUT, url)
                    .timeout(CONNECT_TIMEOUT * 1000);
            
            // 添加请求头
            if (headers != null && !headers.isEmpty()) {
                request.addHeaders(headers);
            }
            
            // 添加上传数据
            if (data != null && data.length > 0) {
                request.body(data);
            }
            
            HttpResponse response = request.execute();
            
            if (response.getStatus() != 200) {
                throw new Exception("HTTP请求失败: " + response.getStatus());
            }
            
            return response.body();
        } catch (Exception e) {
            throw new Exception("PUT请求失败: " + e.getMessage(), e);
        }
    }
    
    /**
     * 解析响应（支持JSON和XML格式）
     *
     * @param response 响应字符串
     * @return 解析后的JSON对象
     * @throws Exception 解析异常
     */
    public static JSONObject parseJsonResponse(String response) throws Exception {
        if (StrUtil.isBlank(response)) {
            logDebug("响应为空");
            throw new Exception("响应为空");
        }
        
        logDebug("开始解析响应，长度: " + response.length());
        logDebug("响应内容前100字符: " + (response.length() > 100 ? response.substring(0, 100) + "..." : response));
        
        try {
            // 检查是否是XML响应
            if (response.trim().startsWith("<?xml")) {
                logDebug("检测到XML响应格式");
                JSONObject result = xmlToJson(response);
                logDebug("XML解析结果: " + result.toString());
                return result;
            }

            logDebug("检测到JSON响应格式");
            JSONObject result = JSONUtil.parseObj(response);
            logDebug("JSON解析结果: " + result.toString());
            return result;
        } catch (Exception e) {
            logDebug("解析响应失败: " + e.getMessage());
            throw new Exception("解析响应失败: " + e.getMessage(), e);
        }
    }
    
    /**
     * 记录调试日志
     *
     * @param message 日志消息
     */
    private static void logDebug(String message) {
        if (DEBUG_ENABLED) {
            logger.log(Level.INFO, "[HttpUtils-DEBUG] " + message);
        }
    }
    
    /**
     * 记录调试日志（带格式化）
     *
     * @param format 格式化字符串
     * @param args 参数
     */
    private static void logDebug(String format, Object... args) {
        if (DEBUG_ENABLED) {
            logger.log(Level.INFO, "[HttpUtils-DEBUG] " + String.format(format, args));
        }
    }
    
    /**
     * 解析XML响应并转换为JSON格式
     *
     * @param xmlResponse XML响应字符串
     * @return 转换后的JSON对象
     * @throws Exception 解析异常
     */
    private static JSONObject parseXmlResponse(String xmlResponse) throws Exception {
        try {
            // 使用通用XML转JSON方法
            return xmlToJson(xmlResponse);
            
        } catch (Exception e) {
            throw new Exception("解析XML响应失败: " + e.getMessage(), e);
        }
    }
    
    /**
     * 通用XML转JSON方法
     * 支持多层嵌套XML结构，自动转换为对应的JSON格式
     *
     * @param xmlString XML字符串
     * @return JSON对象
     * @throws Exception 解析异常
     */
    private static JSONObject xmlToJson(String xmlString) throws Exception {
        // 移除XML声明
        String xmlContent = xmlString.replaceAll("<\\?xml[^>]*\\?>", "").trim();
        
        logDebug("移除XML声明后的内容: " + xmlContent);
        
        // 如果内容为空，返回空JSON对象
        if (StrUtil.isBlank(xmlContent)) {
            logDebug("XML内容为空，返回空JSON对象");
            return new JSONObject();
        }
        
        // 解析XML内容
        JSONObject result = parseXmlContent(xmlContent);
        logDebug("XML解析完成，结果: " + result.toString());
        return result;
    }
    
    /**
     * 解析XML内容
     *
     * @param xmlContent XML内容（不含声明）
     * @return JSON对象
     */
    private static JSONObject parseXmlContent(String xmlContent) {
        JSONObject result = new JSONObject();
        
        logDebug("开始解析XML内容，长度: " + xmlContent.length());
        
        // 查找第一个根标签
        int rootStart = xmlContent.indexOf('<');
        if (rootStart == -1) {
            logDebug("未找到根标签开始位置");
            return result;
        }
        
        int rootEnd = xmlContent.indexOf('>', rootStart);
        if (rootEnd == -1) {
            logDebug("未找到根标签结束位置");
            return result;
        }
        
        String rootTag = xmlContent.substring(rootStart + 1, rootEnd);
        logDebug("根标签名: " + rootTag);
        
        // 检查是否是自闭合标签
        if (xmlContent.charAt(rootEnd - 1) == '/') {
            logDebug("检测到自闭合标签: " + rootTag);
            // 自闭合标签，无内容
            return result;
        }
        
        // 查找对应的结束标签
        String endTag = "</" + rootTag + ">";
        int contentStart = rootEnd + 1;
        int contentEnd = xmlContent.lastIndexOf(endTag);
        
        if (contentEnd == -1) {
            logDebug("未找到结束标签: " + endTag);
            // 没有找到结束标签，可能是自闭合标签或格式错误
            return result;
        }
        
        String content = xmlContent.substring(contentStart, contentEnd).trim();
        logDebug("根标签内容: " + (content.length() > 100 ? content.substring(0, 100) + "..." : content));
        
        // 解析标签内容
        parseTagContent(rootTag, content, result);
        
        return result.getJSONObject(rootTag);
    }
    
    /**
     * 解析标签内容
     *
     * @param tagName 标签名
     * @param content 标签内容
     * @param result 结果JSON对象
     */
    private static void parseTagContent(String tagName, String content, JSONObject result) {
        logDebug("解析标签: " + tagName + ", 内容长度: " + content.length());
        
        // 检查内容是否包含子标签
        if (content.contains("<")) {
            logDebug("标签 " + tagName + " 包含子标签，进行递归解析");
            // 包含子标签，递归解析
            JSONObject childObject = new JSONObject();
            parseChildren(content, childObject);
            result.set(tagName, childObject);
            logDebug("标签 " + tagName + " 解析完成，子对象: " + childObject.toString());
        } else {
            // 纯文本内容，进行类型转换
            Object convertedValue = convertXmlValue(content);
            result.set(tagName, convertedValue);
            logDebug("标签 " + tagName + " 解析完成，值: " + convertedValue + " (类型: " + convertedValue.getClass().getSimpleName() + ")");
        }
    }
    
    /**
     * 递归解析子标签
     *
     * @param content 父标签内容
     * @param parentResult 父JSON对象
     */
    private static void parseChildren(String content, JSONObject parentResult) {
        int index = 0;
        int contentLength = content.length();
        int childCount = 0;
        
        logDebug("开始解析子标签，内容长度: " + contentLength);
        
        while (index < contentLength) {
            // 跳过空白字符
            while (index < contentLength && Character.isWhitespace(content.charAt(index))) {
                index++;
            }
            
            if (index >= contentLength) {
                logDebug("解析子标签完成，共解析 " + childCount + " 个子标签");
                break;
            }
            
            // 查找下一个标签开始
            if (content.charAt(index) != '<') {
                index++;
                continue;
            }
            
            int tagStart = index;
            int tagEnd = content.indexOf('>', tagStart);
            
            if (tagEnd == -1) {
                logDebug("未找到标签结束位置");
                break;
            }
            
            String tagDeclaration = content.substring(tagStart, tagEnd + 1);
            logDebug("发现标签声明 " + (++childCount) + ": " + tagDeclaration);
            
            // 检查是否是注释或CDATA
            if (tagDeclaration.startsWith("<!--") || tagDeclaration.startsWith("<![CDATA[")) {
                // 跳过注释或CDATA
                if (tagDeclaration.startsWith("<!--")) {
                    int commentEnd = content.indexOf("-->", tagStart);
                    if (commentEnd != -1) {
                        index = commentEnd + 3;
                        logDebug("跳过注释，长度: " + (commentEnd - tagStart + 3));
                    } else {
                        break;
                    }
                } else if (tagDeclaration.startsWith("<![CDATA[")) {
                    int cdataEnd = content.indexOf("]]>", tagStart);
                    if (cdataEnd != -1) {
                        index = cdataEnd + 3;
                        logDebug("跳过CDATA，长度: " + (cdataEnd - tagStart + 3));
                    } else {
                        break;
                    }
                }
                continue;
            }
            
            // 检查是否是结束标签
            if (tagDeclaration.startsWith("</")) {
                logDebug("遇到结束标签，停止解析: " + tagDeclaration);
                // 结束标签，返回
                break;
            }
            
            // 提取标签名
            String tagName;
            if (tagDeclaration.endsWith("/>")) {
                // 自闭合标签
                tagName = tagDeclaration.substring(1, tagDeclaration.length() - 2);
                parentResult.set(tagName, "");
                index = tagEnd + 1;
                logDebug("自闭合标签: " + tagName);
                continue;
            } else {
                // 开始标签
                int spaceIndex = tagDeclaration.indexOf(' ');
                if (spaceIndex != -1) {
                    tagName = tagDeclaration.substring(1, spaceIndex);
                } else {
                    tagName = tagDeclaration.substring(1, tagDeclaration.length() - 1);
                }
            }
            
            // 查找对应的结束标签
            String endTag = "</" + tagName + ">";
            int endTagIndex = content.indexOf(endTag, tagEnd);
            
            if (endTagIndex == -1) {
                logDebug("未找到结束标签: " + endTag + "，可能是自闭合标签");
                // 没有找到结束标签，可能是自闭合标签
                parentResult.set(tagName, "");
                index = tagEnd + 1;
                continue;
            }
            
            // 提取标签内容
            String tagContent = content.substring(tagEnd + 1, endTagIndex).trim();
            
            // 解析标签内容
            parseTagContent(tagName, tagContent, parentResult);
            
            // 移动到下一个位置
            index = endTagIndex + endTag.length();
        }
        
        logDebug("子标签解析完成，最终结果: " + parentResult.toString());
    }
    
    /**
     * 从XML中提取UUID信息
     *
     * @param xmlResponse XML响应字符串
     * @return UUID字符串
     */
    private static String extractUuidFromXml(String xmlResponse) {
        // 匹配UUID信息格式
        // 示例: <uuidInfo><uuid>https://open.e.189.cn/api/account/qrClinentLogin.do?paras=new_uuid%3Db81urjxkwhj4m14g%7C8013418323</uuid></uuidInfo></uuidInfo>
        Pattern uuidPattern = Pattern.compile("<uuid>([^<]+)</uuid>", Pattern.CASE_INSENSITIVE);
        Matcher matcher = uuidPattern.matcher(xmlResponse);
        
        if (matcher.find()) {
            return matcher.group(1).trim();
        }
        
        // 尝试其他可能的UUID格式
        Pattern urlPattern = Pattern.compile("https://[^\\s<]+", Pattern.CASE_INSENSITIVE);
        Matcher urlMatcher = urlPattern.matcher(xmlResponse);
        
        if (urlMatcher.find()) {
            return urlMatcher.group(0).trim();
        }
        
        return "";
    }
    
    /**
     * 将XML响应转换为JSON对象
     *
     * @param xmlResponse XML响应字符串
     * @param result JSON结果对象
     */
    private static void parseXmlToJson(String xmlResponse, JSONObject result) {
        // 提取常见的XML标签
        String[] tags = {"code", "message", "sessionId", "token", "accessToken", "refreshToken", "userId", "success", "error"};
        
        for (String tag : tags) {
            String value = extractXmlValue(xmlResponse, tag);
            if (StrUtil.isNotBlank(value)) {
                // 尝试转换为数字或布尔值
                Object convertedValue = convertXmlValue(value);
                result.set(tag, convertedValue);
            }
        }
    }
    
    /**
     * 转换XML值为适当的Java类型
     *
     * @param value XML值字符串
     * @return 转换后的值
     */
    private static Object convertXmlValue(String value) {
        if (StrUtil.isBlank(value)) {
            return value;
        }
        
        // 尝试转换为布尔值
        if ("true".equalsIgnoreCase(value) || "false".equalsIgnoreCase(value)) {
            return Boolean.parseBoolean(value);
        }
        
        // 尝试转换为数字
        try {
            if (value.contains(".")) {
                return Double.parseDouble(value);
            } else {
                return Long.parseLong(value);
            }
        } catch (NumberFormatException e) {
            // 不是数字，返回原字符串
            return value;
        }
    }
    
    /**
     * 检查响应是否包含错误
     * 
     * @param responseJson JSON响应对象
     * @return 是否包含错误
     */
    public static boolean hasError(JSONObject responseJson) {
        if (responseJson == null) {
            return true;
        }
        
        // 检查多种错误格式
        if (responseJson.containsKey("isError") && responseJson.getBool("isError")) {
            return true;
        }
        
        if (responseJson.containsKey("res_code")) {
            Object resCode = responseJson.get("res_code");
            if (resCode instanceof Number) {
                return ((Number) resCode).intValue() != 0;
            } else if (resCode instanceof String) {
                return !StrUtil.isBlank((String) resCode);
            }
        }
        
        if (responseJson.containsKey("code")) {
            String code = responseJson.getStr("code");
            return !StrUtil.equals(code, "SUCCESS") && !StrUtil.isBlank(code);
        }
        
        if (responseJson.containsKey("errorCode")) {
            return !StrUtil.isBlank(responseJson.getStr("errorCode"));
        }
        
        return false;
    }
    
    /**
     * 获取错误消息
     * 
     * @param responseJson JSON响应对象
     * @return 错误消息
     */
    public static String getErrorMessage(JSONObject responseJson) {
        if (responseJson == null) {
            return "未知错误";
        }
        
        // 尝试多种错误消息格式
        if (responseJson.containsKey("res_message")) {
            return responseJson.getStr("res_message");
        }
        
        if (responseJson.containsKey("message")) {
            return responseJson.getStr("message");
        }
        
        if (responseJson.containsKey("msg")) {
            return responseJson.getStr("msg");
        }
        
        if (responseJson.containsKey("errorMsg")) {
            return responseJson.getStr("errorMsg");
        }
        
        return "未知错误";
    }
    
    /**
     * 从XML字符串中提取指定标签的值
     * 
     * @param xml XML字符串
     * @param tag 标签名
     * @return 标签值
     */
    private static String extractXmlValue(String xml, String tag) {
        String startTag = "<" + tag + ">";
        String endTag = "</" + tag + ">";
        
        int startIndex = xml.indexOf(startTag);
        if (startIndex == -1) {
            return "";
        }
        
        startIndex += startTag.length();
        int endIndex = xml.indexOf(endTag, startIndex);
        if (endIndex == -1) {
            return "";
        }
        
        return xml.substring(startIndex, endIndex);
    }
}